
/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2022原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.beans.factory;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * Convenience methods operating on bean factories, in particular
 * on the {@link ListableBeanFactory} interface.
 *
 * <p>Returns bean counts, bean names or bean instances,
 * taking into account the nesting hierarchy of a bean factory
 * (which the methods defined on the ListableBeanFactory interface don't,
 * in contrast to the methods defined on the BeanFactory interface).
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Chris Beams
 * @since 04.07.2003
 */
/**
 *特别是在豆制品厂操作的便利方法
 *在｛@link ListableBeanFactory｝接口上。
 *
 *＜p＞返回bean计数、bean名称或bean实例，
 *考虑bean工厂的嵌套层次结构
 *（ListableBeanFactory接口上定义的方法没有，
 *与BeanFactory接口上定义的方法不同）。
 *
 *@作者Rod Johnson
 *@作者Juergen Hoeller
 *@作者Chris Beams
 *@自2003年7月4日
 */
public abstract class BeanFactoryUtils {

	/**
	 * Separator for generated bean names. If a class name or parent name is not
	 * unique, "#1", "#2" etc will be appended, until the name becomes unique.
	 */
	/**
	 *生成的bean名称的分隔符。如果类名或父名称不是
	 *unique、“#1”、“#2”等将被追加，直到名称变得唯一。
	 */
	public static final String GENERATED_BEAN_NAME_SEPARATOR = "#";

	/**
	 * Cache from name with factory bean prefix to stripped name without dereference.
	 * @since 5.1
	 * @see BeanFactory#FACTORY_BEAN_PREFIX
	 */
	/**
	 *从带有工厂bean前缀的名称缓存到不带解引用的剥离名称。
	 *@自5.1
	 *@参见BeanFactory#FACTORY_BEAN_PREFIX
	 */
	private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();


	/**
	 * Return whether the given name is a factory dereference
	 * (beginning with the factory dereference prefix).
	 * @param name the name of the bean
	 * @return whether the given name is a factory dereference
	 * @see BeanFactory#FACTORY_BEAN_PREFIX
	 */
	/**
	 *返回给定名称是否为工厂取消引用
	 *（以工厂取消引用前缀开头）。
	 *@param name bean的名称
	 *@return给定名称是否为工厂解引用
	 *@参见BeanFactory#FACTORY_BEAN_PREFIX
	 */
	public static boolean isFactoryDereference(@Nullable String name) {
		return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
	}

	/**
	 * Return the actual bean name, stripping out the factory dereference
	 * prefix (if any, also stripping repeated factory prefixes if found).
	 * @param name the name of the bean
	 * @return the transformed name
	 * @see BeanFactory#FACTORY_BEAN_PREFIX
	 */
	/**
	 *返回实际的bean名称，去掉工厂引用
	 *前缀（如果有的话，如果发现重复的工厂前缀，也可以去掉）。
	 *@param name bean的名称
	 *@返回转换后的名称
	 *@参见BeanFactory#FACTORY_BEAN_PREFIX
	 */
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

	/**
	 * Return whether the given name is a bean name which has been generated
	 * by the default naming strategy (containing a "#..." part).
	 * @param name the name of the bean
	 * @return whether the given name is a generated bean name
	 * @see #GENERATED_BEAN_NAME_SEPARATOR
	 * @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils#generateBeanName
	 * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator
	 */
	/**
	 *返回给定名称是否为已生成的bean名称
	 *默认命名策略（包含“#…”部分）。
	 *@param name bean的名称
	 *@return给定名称是否为生成的bean名称
	 *@参见#GENERATED_EAN_NAME_SEPARATOR
	 *@see org.springframework.beans.factory.support.BeanDefinitionReaderUtils#generateBeanName
	 *@参见org.springframework.beans.factory.support.DefaultBeanNameGenerator
	 */
	public static boolean isGeneratedBeanName(@Nullable String name) {
		return (name != null && name.contains(GENERATED_BEAN_NAME_SEPARATOR));
	}

	/**
	 * Extract the "raw" bean name from the given (potentially generated) bean name,
	 * excluding any "#..." suffixes which might have been added for uniqueness.
	 * @param name the potentially generated bean name
	 * @return the raw bean name
	 * @see #GENERATED_BEAN_NAME_SEPARATOR
	 */
	/**
	 *从给定的（可能生成的）bean名称中提取“原始”bean名称，
	 *排除可能为唯一性而添加的任何“#…”后缀。
	 *@param name潜在生成的bean名称
	 *@return原始bean名称
	 *@参见#GENERATED_EAN_NAME_SEPARATOR
	 */
	public static String originalBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		int separatorIndex = name.indexOf(GENERATED_BEAN_NAME_SEPARATOR);
		return (separatorIndex != -1 ? name.substring(0, separatorIndex) : name);
	}


	// Retrieval of bean names
	// 检索bean名称

	/**
	 * Count all beans in any hierarchy in which this factory participates.
	 * Includes counts of ancestor bean factories.
	 * <p>Beans that are "overridden" (specified in a descendant factory
	 * with the same name) are only counted once.
	 * @param lbf the bean factory
	 * @return count of beans including those defined in ancestor factories
	 * @see #beanNamesIncludingAncestors
	 */
	/**
	 *计算此工厂参与的任何层次结构中的所有bean。
	 *包括祖先bean工厂的计数。
	 *＜p＞被“重写”的bean（在后代工厂中指定
	 *同名）仅计数一次。
	 *@param lbf豆工厂
	 *@return bean计数，包括在祖先工厂中定义的bean
	 *@see#beanNames包含祖先
	 */
	public static int countBeansIncludingAncestors(ListableBeanFactory lbf) {
		return beanNamesIncludingAncestors(lbf).length;
	}

	/**
	 * Return all bean names in the factory, including ancestor factories.
	 * @param lbf the bean factory
	 * @return the array of matching bean names, or an empty array if none
	 * @see #beanNamesForTypeIncludingAncestors
	 */
	/**
	 *返回工厂中的所有bean名称，包括祖先工厂。
	 *@param lbf豆工厂
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@参见#beanNamesForTypeInclusingAncestors
	 */
	public static String[] beanNamesIncludingAncestors(ListableBeanFactory lbf) {
		return beanNamesForTypeIncludingAncestors(lbf, Object.class);
	}

	/**
	 * Get all bean names for the given type, including those defined in ancestor
	 * factories. Will return unique names in case of overridden bean definitions.
	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
	 * will get initialized. If the object created by the FactoryBean doesn't match,
	 * the raw FactoryBean itself will be matched against the type.
	 * <p>This version of {@code beanNamesForTypeIncludingAncestors} automatically
	 * includes prototypes and FactoryBeans.
	 * @param lbf the bean factory
	 * @param type the type that beans must match (as a {@code ResolvableType})
	 * @return the array of matching bean names, or an empty array if none
	 * @since 4.2
	 * @see ListableBeanFactory#getBeanNamesForType(ResolvableType)
	 */
	/**
	 *获取给定类型的所有bean名称，包括祖先中定义的名称
	 *工厂。在重写bean定义的情况下，将返回唯一的名称。
	 *＜p＞考虑FactoryBean创建的对象，这意味着FactoryBean
	 *将被初始化。如果FactoryBean创建的对象不匹配，
	 *原始FactoryBean本身将与类型匹配。
	 *＜p＞此版本的｛@code beanNamesForTypeInclusingAncestors｝自动
	 *包括原型和FactoryBean。
	 *@param lbf豆工厂
	 *@param类型bean必须匹配的类型（作为｛@code ResolutibleType｝）
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@自4.2
	 *@see ListableBeanFactory#getBeanNameForType（可解析类型）
	 */
	public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, ResolvableType type) {
		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type);
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(pbf, type);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

	/**
	 * Get all bean names for the given type, including those defined in ancestor
	 * factories. Will return unique names in case of overridden bean definitions.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
	 * flag is set, which means that FactoryBeans will get initialized. If the
	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
	 * will be matched against the type. If "allowEagerInit" is not set,
	 * only raw FactoryBeans will be checked (which doesn't require initialization
	 * of each FactoryBean).
	 * @param lbf the bean factory
	 * @param type the type that beans must match (as a {@code ResolvableType})
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @return the array of matching bean names, or an empty array if none
	 * @since 5.2
	 * @see ListableBeanFactory#getBeanNamesForType(ResolvableType, boolean, boolean)
	 */
	/**
	 *获取给定类型的所有bean名称，包括祖先中定义的名称
	 *工厂。在重写bean定义的情况下，将返回唯一的名称。
	 *＜p＞如果“allowEagleInit”
	 *标志被设置，这意味着FactoryBean将被初始化。如果
	 *FactoryBean创建的对象不匹配，原始FactoryBean本身
	 *将与类型匹配。如果未设置“allowEagleInit”，
	 *只检查原始FactoryBean（不需要初始化
	 *每个FactoryBean的）。
	 *@param lbf豆工厂
	 *@param类型bean必须匹配的类型（作为｛@code ResolutibleType｝）
	 *@param includeOnSingleton是否也包括原型或作用域bean
	 *或者仅仅是单体（也适用于FactoryBean）
	 *@param allowEagleInit是否初始化＜i＞lazy init singletons＜/i＞和
	 *<i>由FactoryBeans</i>创建的对象（或由带有
	 *“factorybean”引用）。注意FactoryBean需要
	 *急切地初始化以确定它们的类型：所以请注意传入“true”
	 *for此标志将初始化FactoryBean和“factorybean”引用。
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@自5.2
	 *@see ListableBeanFactory#getBeanNameForType（可解析类型，布尔值，布尔值）
	 */
	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						pbf, type, includeNonSingletons, allowEagerInit);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

	/**
	 * Get all bean names for the given type, including those defined in ancestor
	 * factories. Will return unique names in case of overridden bean definitions.
	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
	 * will get initialized. If the object created by the FactoryBean doesn't match,
	 * the raw FactoryBean itself will be matched against the type.
	 * <p>This version of {@code beanNamesForTypeIncludingAncestors} automatically
	 * includes prototypes and FactoryBeans.
	 * @param lbf the bean factory
	 * @param type the type that beans must match (as a {@code Class})
	 * @return the array of matching bean names, or an empty array if none
	 * @see ListableBeanFactory#getBeanNamesForType(Class)
	 */
	/**
	 *获取给定类型的所有bean名称，包括祖先中定义的名称
	 *工厂。在重写bean定义的情况下，将返回唯一的名称。
	 *＜p＞考虑FactoryBean创建的对象，这意味着FactoryBean
	 *将被初始化。如果FactoryBean创建的对象不匹配，
	 *原始FactoryBean本身将与类型匹配。
	 *＜p＞此版本的｛@code beanNamesForTypeInclusingAncestors｝自动
	 *包括原型和FactoryBean。
	 *@param lbf豆工厂
	 *@param类型bean必须匹配的类型（作为｛@code Class｝）
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@see ListableBeanFactory#getBeanNameForType（类）
	 */
	public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type) {
		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type);
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(pbf, type);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

	/**
	 * Get all bean names for the given type, including those defined in ancestor
	 * factories. Will return unique names in case of overridden bean definitions.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
	 * flag is set, which means that FactoryBeans will get initialized. If the
	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
	 * will be matched against the type. If "allowEagerInit" is not set,
	 * only raw FactoryBeans will be checked (which doesn't require initialization
	 * of each FactoryBean).
	 * @param lbf the bean factory
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @param type the type that beans must match
	 * @return the array of matching bean names, or an empty array if none
	 * @see ListableBeanFactory#getBeanNamesForType(Class, boolean, boolean)
	 */
	/**
	 *获取给定类型的所有bean名称，包括祖先中定义的名称
	 *工厂。在重写bean定义的情况下，将返回唯一的名称。
	 *＜p＞如果“allowEagleInit”
	 *标志被设置，这意味着FactoryBean将被初始化。如果
	 *FactoryBean创建的对象不匹配，原始FactoryBean本身
	 *将与类型匹配。如果未设置“allowEagleInit”，
	 *只检查原始FactoryBean（不需要初始化
	 *每个FactoryBean的）。
	 *@param lbf豆工厂
	 *@param includeOnSingleton是否也包括原型或作用域bean
	 *或者仅仅是单体（也适用于FactoryBean）
	 *@param allowEagleInit是否初始化＜i＞lazy init singletons＜/i＞和
	 *<i>由FactoryBeans</i>创建的对象（或由带有
	 *“factorybean”引用）。注意FactoryBean需要
	 *急切地初始化以确定它们的类型：所以请注意传入“true”
	 *for此标志将初始化FactoryBean和“factorybean”引用。
	 *@param type bean必须匹配的类型
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@see ListableBeanFactory#getBeanNameForType（类，布尔值，布尔值）
	 */
	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						pbf, type, includeNonSingletons, allowEagerInit);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

	/**
	 * Get all bean names whose {@code Class} has the supplied {@link Annotation}
	 * type, including those defined in ancestor factories, without creating any bean
	 * instances yet. Will return unique names in case of overridden bean definitions.
	 * @param lbf the bean factory
	 * @param annotationType the type of annotation to look for
	 * @return the array of matching bean names, or an empty array if none
	 * @since 5.0
	 * @see ListableBeanFactory#getBeanNamesForAnnotation(Class)
	 */
	/**
	 *获取其｛@code Class｝具有提供的｛@link Annotation｝的所有bean名称
	 *类型，包括在祖先工厂中定义的类型，而不创建任何bean
	 *实例。在重写bean定义的情况下，将返回唯一的名称。
	 *@param lbf豆工厂
	 *@param annotation键入要查找的注释类型
	 *@返回匹配bean名称的数组，如果没有，则返回空数组
	 *@自5.0
	 *@see ListableBeanFactory#getBeanNameForAnnotation（类）
	 */
	public static String[] beanNamesForAnnotationIncludingAncestors(
			ListableBeanFactory lbf, Class<? extends Annotation> annotationType) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForAnnotation(annotationType);
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				String[] parentResult = beanNamesForAnnotationIncludingAncestors(pbf, annotationType);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}


	// Retrieval of bean instances
	// bean实例的检索

	/**
	 * Return all beans of the given type or subtypes, also picking up beans defined in
	 * ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
	 * The returned Map will only contain beans of this type.
	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
	 * will get initialized. If the object created by the FactoryBean doesn't match,
	 * the raw FactoryBean itself will be matched against the type.
	 * <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
	 * i.e. such beans will be returned from the lowest factory that they are being found in,
	 * hiding corresponding beans in ancestor factories.</b> This feature allows for
	 * 'replacing' beans by explicitly choosing the same bean name in a child factory;
	 * the bean in the ancestor factory won't be visible then, not even for by-type lookups.
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @return the Map of matching bean instances, or an empty Map if none
	 * @throws BeansException if a bean could not be created
	 * @see ListableBeanFactory#getBeansOfType(Class)
	 */
	/**
	 *返回给定类型或子类型的所有bean，并拾取中定义的bean
	 *如果当前bean工厂是HierarchicalBeanFactory，则为祖先bean工厂。
	 *返回的Map将仅包含此类型的bean。
	 *＜p＞考虑FactoryBean创建的对象，这意味着FactoryBean
	 *将被初始化。如果FactoryBean创建的对象不匹配，
	 *原始FactoryBean本身将与类型匹配。
	 *＜p＞＜b＞注意：相同名称的bean在“最低”工厂级别优先，
	 *即，这些豆子将从它们所在的最低工厂返回，
	 *在祖先工厂中隐藏相应的bean</b> 此功能允许
	 *通过在子工厂中显式选择相同的bean名称来“替换”bean；
	 *祖先工厂中的bean将不可见，甚至对于按类型查找也不可见。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@return匹配bean实例的Map，如果没有，则返回空Map
	 *如果无法创建bean，@throws BeansException
	 *@see ListableBeanFactory#getBeanOfType（类）
	 */
	public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
			throws BeansException {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> result = new LinkedHashMap<>(4);
		result.putAll(lbf.getBeansOfType(type));
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				Map<String, T> parentResult = beansOfTypeIncludingAncestors(pbf, type);
				parentResult.forEach((beanName, beanInstance) -> {
					if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
						result.put(beanName, beanInstance);
					}
				});
			}
		}
		return result;
	}

	/**
	 * Return all beans of the given type or subtypes, also picking up beans defined in
	 * ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
	 * The returned Map will only contain beans of this type.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
	 * which means that FactoryBeans will get initialized. If the object created by the
	 * FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
	 * type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
	 * (which doesn't require initialization of each FactoryBean).
	 * <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
	 * i.e. such beans will be returned from the lowest factory that they are being found in,
	 * hiding corresponding beans in ancestor factories.</b> This feature allows for
	 * 'replacing' beans by explicitly choosing the same bean name in a child factory;
	 * the bean in the ancestor factory won't be visible then, not even for by-type lookups.
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @return the Map of matching bean instances, or an empty Map if none
	 * @throws BeansException if a bean could not be created
	 * @see ListableBeanFactory#getBeansOfType(Class, boolean, boolean)
	 */
	/**
	 *返回给定类型或子类型的所有bean，并拾取中定义的bean
	 *如果当前bean工厂是HierarchicalBeanFactory，则为祖先bean工厂。
	 *返回的Map将仅包含此类型的bean。
	 *＜p＞如果设置了“allowEagleInit”标志，则考虑FactoryBean创建的对象，
	 *这意味着FactoryBean将被初始化。如果由
	 *FactoryBean不匹配，原始FactoryBean本身将与
	 *类型。如果未设置“allowEagleInit”，则只检查原始FactoryBean
	 *（这不需要初始化每个FactoryBean）。
	 *＜p＞＜b＞注意：相同名称的bean在“最低”工厂级别优先，
	 *即，这些豆子将从它们所在的最低工厂返回，
	 *在祖先工厂中隐藏相应的bean</b> 此功能允许
	 *通过在子工厂中显式选择相同的bean名称来“替换”bean；
	 *祖先工厂中的bean将不可见，甚至对于按类型查找也不可见。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@param includeOnSingleton是否也包括原型或作用域bean
	 *或者仅仅是单体（也适用于FactoryBean）
	 *@param allowEagleInit是否初始化＜i＞lazy init singletons＜/i＞和
	 *<i>由FactoryBeans</i>创建的对象（或由带有
	 *“factorybean”引用）。注意FactoryBean需要
	 *急切地初始化以确定它们的类型：所以请注意传入“true”
	 *for此标志将初始化FactoryBean和“factorybean”引用。
	 *@return匹配bean实例的Map，如果没有，则返回空Map
	 *如果无法创建bean，@throws BeansException
	 *@see ListableBeanFactory#getBeanOfType（类、布尔值、布尔值）
	 */
	public static <T> Map<String, T> beansOfTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> result = new LinkedHashMap<>(4);
		result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
		if (lbf instanceof HierarchicalBeanFactory hbf) {
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory pbf) {
				Map<String, T> parentResult = beansOfTypeIncludingAncestors(pbf, type, includeNonSingletons, allowEagerInit);
				parentResult.forEach((beanName, beanInstance) -> {
					if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
						result.put(beanName, beanInstance);
					}
				});
			}
		}
		return result;
	}

	/**
	 * Return a single bean of the given type or subtypes, also picking up beans
	 * defined in ancestor bean factories if the current bean factory is a
	 * HierarchicalBeanFactory. Useful convenience method when we expect a
	 * single bean and don't care about the bean name.
	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
	 * will get initialized. If the object created by the FactoryBean doesn't match,
	 * the raw FactoryBean itself will be matched against the type.
	 * <p>This version of {@code beanOfTypeIncludingAncestors} automatically includes
	 * prototypes and FactoryBeans.
	 * <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
	 * i.e. such beans will be returned from the lowest factory that they are being found in,
	 * hiding corresponding beans in ancestor factories.</b> This feature allows for
	 * 'replacing' beans by explicitly choosing the same bean name in a child factory;
	 * the bean in the ancestor factory won't be visible then, not even for by-type lookups.
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @return the matching bean instance
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 * @throws BeansException if the bean could not be created
	 * @see #beansOfTypeIncludingAncestors(ListableBeanFactory, Class)
	 */
	/**
	 *返回给定类型或子类型的单个bean，同时拾取bean
	 *如果当前bean工厂是
	 *层次结构BeanFactory。当我们期望
	 *单个bean，不关心bean名称。
	 *＜p＞考虑FactoryBean创建的对象，这意味着FactoryBean
	 *将被初始化。如果FactoryBean创建的对象不匹配，
	 *原始FactoryBean本身将与类型匹配。
	 *＜p＞此版本的｛@code beanOfTypeIncludedingAncestors｝自动包含
	 *原型和FactoryBean。
	 *＜p＞＜b＞注意：相同名称的bean在“最低”工厂级别优先，
	 *即，这些豆子将从它们所在的最低工厂返回，
	 *在祖先工厂中隐藏相应的bean</b> 此功能允许
	 *通过在子工厂中显式选择相同的bean名称来“替换”bean；
	 *祖先工厂中的bean将不可见，甚至对于按类型查找也不可见。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@return匹配的bean实例
	 *如果找不到给定类型的bean，@throws NoSuchBeanDefinitionException
	 *如果找到多个给定类型的bean，@throws NoUniqueBeanDefinitionException
	 *如果无法创建bean，@throws BeansException
	 *@see#beansOfTypeIncludedingAncestors（ListableBeanFactory，类）
	 */
	public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
			throws BeansException {

		Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type);
		return uniqueBean(type, beansOfType);
	}

	/**
	 * Return a single bean of the given type or subtypes, also picking up beans
	 * defined in ancestor bean factories if the current bean factory is a
	 * HierarchicalBeanFactory. Useful convenience method when we expect a
	 * single bean and don't care about the bean name.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
	 * which means that FactoryBeans will get initialized. If the object created by the
	 * FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
	 * type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
	 * (which doesn't require initialization of each FactoryBean).
	 * <p><b>Note: Beans of the same name will take precedence at the 'lowest' factory level,
	 * i.e. such beans will be returned from the lowest factory that they are being found in,
	 * hiding corresponding beans in ancestor factories.</b> This feature allows for
	 * 'replacing' beans by explicitly choosing the same bean name in a child factory;
	 * the bean in the ancestor factory won't be visible then, not even for by-type lookups.
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @return the matching bean instance
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 * @throws BeansException if the bean could not be created
	 * @see #beansOfTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
	 */
	/**
	 *返回给定类型或子类型的单个bean，同时拾取bean
	 *如果当前bean工厂是
	 *层次结构BeanFactory。当我们期望
	 *单个bean，不关心bean名称。
	 *＜p＞如果设置了“allowEagleInit”标志，则考虑FactoryBean创建的对象，
	 *这意味着FactoryBean将被初始化。如果由
	 *FactoryBean不匹配，原始FactoryBean本身将与
	 *类型。如果未设置“allowEagleInit”，则只检查原始FactoryBean
	 *（这不需要初始化每个FactoryBean）。
	 *＜p＞＜b＞注意：相同名称的bean在“最低”工厂级别优先，
	 *即，这些豆子将从它们所在的最低工厂返回，
	 *在祖先工厂中隐藏相应的bean</b> 此功能允许
	 *通过在子工厂中显式选择相同的bean名称来“替换”bean；
	 *祖先工厂中的bean将不可见，甚至对于按类型查找也不可见。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@param includeOnSingleton是否也包括原型或作用域bean
	 *或者仅仅是单体（也适用于FactoryBean）
	 *@param allowEagleInit是否初始化＜i＞lazy init singletons＜/i＞和
	 *<i>由FactoryBeans</i>创建的对象（或由带有
	 *“factorybean”引用）。注意FactoryBean需要
	 *急切地初始化以确定它们的类型：所以请注意传入“true”
	 *for此标志将初始化FactoryBean和“factorybean”引用。
	 *@return匹配的bean实例
	 *如果找不到给定类型的bean，@throws NoSuchBeanDefinitionException
	 *如果找到多个给定类型的bean，@throws NoUniqueBeanDefinitionException
	 *如果无法创建bean，@throws BeansException
	 *@see#beansOfTypeIncludedingAncestors（ListableBeanFactory，Class，boolean，boolean）
	 */
	public static <T> T beanOfTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit);
		return uniqueBean(type, beansOfType);
	}

	/**
	 * Return a single bean of the given type or subtypes, not looking in ancestor
	 * factories. Useful convenience method when we expect a single bean and
	 * don't care about the bean name.
	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
	 * will get initialized. If the object created by the FactoryBean doesn't match,
	 * the raw FactoryBean itself will be matched against the type.
	 * <p>This version of {@code beanOfType} automatically includes
	 * prototypes and FactoryBeans.
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @return the matching bean instance
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 * @throws BeansException if the bean could not be created
	 * @see ListableBeanFactory#getBeansOfType(Class)
	 */
	/**
	 *返回给定类型或子类型的单个bean，而不查找祖先
	 *工厂。当我们期望单个bean和
	 *不要在意bean名称。
	 *＜p＞考虑FactoryBean创建的对象，这意味着FactoryBean
	 *将被初始化。如果FactoryBean创建的对象不匹配，
	 *原始FactoryBean本身将与类型匹配。
	 *＜p＞此版本的｛@code beanOfType｝自动包含
	 *原型和FactoryBean。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@return匹配的bean实例
	 *如果找不到给定类型的bean，@throws NoSuchBeanDefinitionException
	 *如果找到多个给定类型的bean，@throws NoUniqueBeanDefinitionException
	 *如果无法创建bean，@throws BeansException
	 *@see ListableBeanFactory#getBeanOfType（类）
	 */
	public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException {
		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> beansOfType = lbf.getBeansOfType(type);
		return uniqueBean(type, beansOfType);
	}

	/**
	 * Return a single bean of the given type or subtypes, not looking in ancestor
	 * factories. Useful convenience method when we expect a single bean and
	 * don't care about the bean name.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
	 * flag is set, which means that FactoryBeans will get initialized. If the
	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
	 * will be matched against the type. If "allowEagerInit" is not set,
	 * only raw FactoryBeans will be checked (which doesn't require initialization
	 * of each FactoryBean).
	 * @param lbf the bean factory
	 * @param type type of bean to match
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @return the matching bean instance
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 * @throws BeansException if the bean could not be created
	 * @see ListableBeanFactory#getBeansOfType(Class, boolean, boolean)
	 */
	/**
	 *返回给定类型或子类型的单个bean，而不查找祖先
	 *工厂。当我们期望单个bean和
	 *不要在意bean名称。
	 *＜p＞如果“allowEagleInit”
	 *标志被设置，这意味着FactoryBean将被初始化。如果
	 *FactoryBean创建的对象不匹配，原始FactoryBean本身
	 *将与类型匹配。如果未设置“allowEagleInit”，
	 *只检查原始FactoryBean（不需要初始化
	 *每个FactoryBean的）。
	 *@param lbf豆工厂
	 *@param要匹配的bean类型
	 *@param includeOnSingleton是否也包括原型或作用域bean
	 *或者仅仅是单体（也适用于FactoryBean）
	 *@param allowEagleInit是否初始化＜i＞lazy init singletons＜/i＞和
	 *<i>由FactoryBeans</i>创建的对象（或由带有
	 *“factorybean”引用）。注意FactoryBean需要
	 *急切地初始化以确定它们的类型：所以请注意传入“true”
	 *for此标志将初始化FactoryBean和“factorybean”引用。
	 *@return匹配的bean实例
	 *如果找不到给定类型的bean，@throws NoSuchBeanDefinitionException
	 *如果找到多个给定类型的bean，@throws NoUniqueBeanDefinitionException
	 *如果无法创建bean，@throws BeansException
	 *@see ListableBeanFactory#getBeanOfType（类、布尔值、布尔值）
	 */
	public static <T> T beanOfType(
			ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit);
		return uniqueBean(type, beansOfType);
	}


	/**
	 * Merge the given bean names result with the given parent result.
	 * @param result the local bean name result
	 * @param parentResult the parent bean name result (possibly empty)
	 * @param hbf the local bean factory
	 * @return the merged result (possibly the local result as-is)
	 * @since 4.3.15
	 */
	/**
	 *将给定的bean名称结果与给定的父结果合并。
	 *@param result本地bean名称结果
	 *@param parentResult父bean名称结果（可能为空）
	 *@param hbf本地bean工厂
	 *@返回合并结果（可能是本地结果）
	 *@自4.3.15
	 */
	private static String[] mergeNamesWithParent(String[] result, String[] parentResult, HierarchicalBeanFactory hbf) {
		if (parentResult.length == 0) {
			return result;
		}
		List<String> merged = new ArrayList<>(result.length + parentResult.length);
		merged.addAll(Arrays.asList(result));
		for (String beanName : parentResult) {
			if (!merged.contains(beanName) && !hbf.containsLocalBean(beanName)) {
				merged.add(beanName);
			}
		}
		return StringUtils.toStringArray(merged);
	}

	/**
	 * Extract a unique bean for the given type from the given Map of matching beans.
	 * @param type type of bean to match
	 * @param matchingBeans all matching beans found
	 * @return the unique bean instance
	 * @throws NoSuchBeanDefinitionException if no bean of the given type was found
	 * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
	 */
	/**
	 *从给定的匹配bean映射中提取给定类型的唯一bean。
	 *@param要匹配的bean类型
	 *@param matchingBeans找到所有匹配的bean
	 *@return唯一的bean实例
	 *如果找不到给定类型的bean，@throws NoSuchBeanDefinitionException
	 *如果找到多个给定类型的bean，@throws NoUniqueBeanDefinitionException
	 */
	private static <T> T uniqueBean(Class<T> type, Map<String, T> matchingBeans) {
		int count = matchingBeans.size();
		if (count == 1) {
			return matchingBeans.values().iterator().next();
		}
		else if (count > 1) {
			throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
		}
		else {
			throw new NoSuchBeanDefinitionException(type);
		}
	}

}
